#pragma once
#include <bitset>
#include <vector>
#include <stdexcept>
namespace can{
enum fmt_e{
    hex = 0,
    groupDisplay =1,
    crc=2
};

class frame
{
public:
    frame(std::bitset<11> identifier, std::vector<unsigned char> data);     //base data frame
    frame(std::bitset<29> extIdentifier, std::vector<unsigned char> data);  //extended data frame
    frame(std::bitset<11> identifier,unsigned long dlc,bool RTR=true);         //base remote frame
    frame(std::bitset<29> extIdentifier, unsigned long dlc, bool RTR=true);    //extended remote frame
    
    frame(std::string rawFrame);    //recv message
    virtual ~frame() =default;

    frame(const frame& src) =default;
    frame& operator=(const frame& rhs)  =default;
    frame(frame&& src) noexcept;
    frame& operator=(frame&& rhs) noexcept;
    
    bool isRTR(int *reqSize=nullptr) const;
    bool isIDE() const;
    bool isACK() const; //return true if frame is received correctly
    frame& fillData(const std::vector<unsigned char> &data);
    friend std::ostream& operator<<(std::ostream& out,const frame& rhs);
    friend bool operator==(const frame& lhs,const frame& rhs);  //compare id、crc(hashed data) and all flags excluding ack.
    std::bitset<3> fmt=0x0UL;
    //错误帧反馈    ---轮询RTR位，通过isRTR公共函数实现
    //过载帧反馈
protected:
//bitset是小端模式 bitset<4> dlc=0x8UL dlc输出1000，dlc[3]输出1。
//CAN网络是大端模式，MSB在先于LSB传输。
    const std::bitset<1> mSOFrame=kDominantBit;
    std::bitset<11> mIdentifier;
    std::bitset<1> mRTR;
    std::bitset<1> mIDE;
    std::bitset<1> mSRR = kRecessiveBit;
    std::bitset<18> mIdentifierExt;
    std::bitset<1> mR0 = kDominantBit;
    std::bitset<1> mR1 = kDominantBit;
    std::bitset<4>  mDLC;
    std::vector<unsigned char> mData;
    std::bitset<15> mCRC =0x0UL;
    const std::bitset<1>  mCRC_del=0x1UL;
    std::bitset<1> mACK = kRecessiveBit;
    const std::bitset<1> mACK_del = kRecessiveBit;
    const std::bitset<7>  mEOFrame=0x7fUL;

    void preCheck(int dlc=-1) const;      //input check set upon network layer
    void postCheck(std::string& rawFrame) const;    //input check set upon physical layer
    bool equal_id(const frame& rhs) const;
    std::bitset<15> calcCRC() const;
    std::string getWholeFrameInOne(bool user=false) const;
private:
    static const unsigned char kDominantBit=0UL;
    static const unsigned char kRecessiveBit=1UL;
};
bool operator!=(const frame& lhs,const frame& rhs);


class port
{
public:
    void setBaudrate(size_t Baudrate=125000);
    void getBaudrate();
    void setFilter(std::bitset<11> Identifier,std::bitset<11> mask);
    void setFilter(std::bitset<29> exIdentifier,std::bitset<29> mask);
    void setLoopback();
    void getLoopback();
    //启用CAN1和CAN0的设置

};

}